home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 12 - 1996 / 12.10 Oct 96 / AdownsJavaObjects / BackdropCanvas.java next >
Encoding:
Text File  |  1996-09-11  |  14.3 KB  |  541 lines  |  [TEXT/R*ch]

  1. /*
  2.  
  3. Listing 2: BackdropCanvas .java
  4.  
  5. BackdropCanvas.java
  6. Define and create a new instance of our drawing canvas.
  7.  
  8. */
  9.  
  10. // Import the generic Java classes.
  11. import java.applet.*;
  12. import java.awt.*;
  13. import java.io.*;
  14. import java.lang.*;
  15.  
  16. //    Our class definition.
  17. //    It is public so it can be used by classes not defined in this file.
  18. //    It is named BackdropCanvas, and is descended from Canvas.
  19. public    class BackdropCanvas extends Canvas
  20. {
  21.  
  22.     //    Several property/variable declarations.
  23.     //    Since these are external to any of our methods within the class,
  24.     //    they can be considered global to those methods.
  25.  
  26.     //    We need to keep track of our background color.
  27.     Color                    theCanvasBackgroundColor = Color.gray;
  28.  
  29.     //    References to objects we will create and draw.
  30.     //    Initialize to null just to be safe.
  31.     DecafObject        theCurrentDecafObject = null;
  32.     DecafObject        theNewDecafObject = null;
  33.     DecafObject        theFirstDecafObject = null;
  34.  
  35.     //    Mouse state and location information.
  36.     boolean                mouseIsDown = false;
  37.     boolean                insideGrow = false;
  38.     int                        xOffset = 0, yOffset = 0;
  39.  
  40.     //    The current color selections for our canvas, panel, button, and text area
  41.     //    backgrounds and foregrounds.
  42.     int                        theColorArray[] = new int[ 7 ];
  43.  
  44.     //    Counters to track how many of each type we have created.
  45.     static    int        thePanelID = 0, theButtonID = 0;     static    int        theTextAreaID = 0;
  46.  
  47.     //    Two sets of declarations used as constants.
  48.     //    One for the type of object we are creating, 
  49.     //    the other for the alignment of any text drawn within that object.
  50.     //    They get passed to new objects during the creation process.
  51.  
  52.     //    theObjectType: 0 = Panel, 1 = Button, 2 = Text Area
  53.     static    int        thePanelType = 0, theButtonType = 1;     static    int        theTextAreaType = 0;
  54.  
  55.     //    theTextAlignment: 0 = Left, 1 = Center, 2 = Right
  56.     static    int        theLeftAlignment = 0;
  57.     static    int        theCenterAlignment = 0;
  58.     static    int        theRightAlignment = 0;
  59.  
  60.  
  61.     //    Our class constructor, or what should happen when a new instance of
  62.     //    this class is created.
  63.     public BackdropCanvas()
  64.     {
  65.         setBackground( theCanvasBackgroundColor );
  66.     }
  67.  
  68.     //    Change our canvas background color on demand.
  69.     public void doSetBackgroundColor( Color theColor )
  70.     {
  71.         theCanvasBackgroundColor = theColor;
  72.         setBackground( theCanvasBackgroundColor );
  73.     }
  74.  
  75.     //    Determine appropriate color when creating new objects.
  76.     //    Refer back to our declaration of theColorArray above.
  77.     public int doFindColor( int itemNo )
  78.     {
  79.         return theColorArray[ itemNo ];
  80.     }
  81.  
  82.     //    Change colors for new and selected objects.
  83.     public boolean doChangeColor( int theItem, int theColor )
  84.     {
  85.         boolean                changedItem = false;
  86.         int                        theObjectType = 0;
  87.         DecafObject        theTempDecafObject = theFirstDecafObject;
  88.  
  89.         while ( theTempDecafObject != null )
  90.         {
  91.             if ( theTempDecafObject.DoGetSelected() )
  92.             {
  93.                 theObjectType =
  94.                         theTempDecafObject.DoGetObjectType();
  95.                 break;
  96.             }
  97.  
  98.             theTempDecafObject =
  99.                     theTempDecafObject.doGetNextDecafObject();
  100.         }
  101.  
  102.         theColorArray[ theItem ] = theColor;
  103.  
  104.         if ( theTempDecafObject != null )
  105.         {
  106.             switch ( theItem )
  107.             {
  108.                 case 1:
  109.                     if ( theObjectType == 0 )
  110.                     {
  111.                         theTempDecafObject.doSetBackColor( theColor );
  112.                         changedItem = true;
  113.                     }
  114.  
  115.                     break;
  116.  
  117.                 case 2:
  118.                     if ( theObjectType == 0 )
  119.                     {
  120.                         theTempDecafObject.doSetTextColor( theColor );
  121.                         changedItem = true;
  122.                     }
  123.  
  124.                     break;
  125.  
  126.                 case 3:
  127.                     if ( theObjectType == 1 )
  128.                     {
  129.                         theTempDecafObject.doSetBackColor( theColor );
  130.                         changedItem = true;
  131.                     }
  132.  
  133.                     break;
  134.  
  135.                 case 4:
  136.                     if ( theObjectType == 1 )
  137.                     {
  138.                         theTempDecafObject.doSetTextColor( theColor );
  139.                         changedItem = true;
  140.                     }
  141.  
  142.                     break;
  143.  
  144.                 case 5:
  145.                     if ( theObjectType == 2 )
  146.                     {
  147.                         theTempDecafObject.doSetBackColor( theColor );
  148.                         changedItem = true;
  149.                     }
  150.  
  151.                     break;
  152.  
  153.                 case 6:
  154.                     if ( theObjectType == 2 )
  155.                     {
  156.                         theTempDecafObject.doSetTextColor( theColor );
  157.                         changedItem = true;
  158.                     }
  159.  
  160.                     break;
  161.  
  162.                 default:
  163.                     break;
  164.             }
  165.         }
  166.  
  167.         if ( changedItem )
  168.             repaint();
  169.  
  170.         return changedItem;
  171.     }
  172.  
  173.     //    For deleting a selected object.
  174.     public boolean doDeleteDecafObject()
  175.     {
  176.  
  177.         //    Long variable names here, which make the code difficult to read.
  178.         //    Replace with shorter names such as tempDC.
  179.         boolean                objectDeleted = false;
  180.         DecafObject        theTempDecafObject = null;
  181.         DecafObject        thePreviousTempDecafObject = null;
  182.         DecafObject        theNextTempDecafObject = null;
  183.     
  184.         //    Walk through our list of objects, looking for the one that is selected.
  185.         //    This code or variations of it will be used in several places within this class.
  186.         //    It is a good candidate for a separate method.
  187.  
  188.         //    In this case, start with the first object in the list.
  189.         //    If it is selected (e.g. the user clicked on it), remove its 
  190.         //    references to the objects before and after it in the list.
  191.         //    Instead, set those objects to point at each other.
  192.         //    That is the purpose of the method DoDeleteDecafObject().
  193.  
  194.         //    Note that special things happen if we are dealing with either:
  195.         //    a. the last object created (theCurrentDecafObject), or
  196.         //    b. the first object in the list (theFirstDecafObject).
  197.  
  198.         theTempDecafObject = theFirstDecafObject;
  199.  
  200.         while ( theTempDecafObject != null )
  201.         {
  202.             if ( theTempDecafObject.DoGetSelected() )
  203.             {
  204.                 thePreviousTempDecafObject =
  205.                         theTempDecafObject.doGetPreviousDecafObject();
  206.  
  207.                 theNextTempDecafObject =
  208.                         theTempDecafObject.doGetNextDecafObject();
  209.  
  210.                 theTempDecafObject.DoDeleteDecafObject();
  211.  
  212.                 if ( theCurrentDecafObject == theTempDecafObject )
  213.                 {
  214.                     if ( thePreviousTempDecafObject != null )
  215.                         theCurrentDecafObject =
  216.                                 thePreviousTempDecafObject;
  217.                     else
  218.                         theCurrentDecafObject = null;
  219.                 }
  220.  
  221.                 if ( theFirstDecafObject == theTempDecafObject )
  222.                 {
  223.                     if ( theNextTempDecafObject != null )
  224.                         theFirstDecafObject = theNextTempDecafObject;
  225.                     else
  226.                         theFirstDecafObject = null;
  227.                 }
  228.  
  229.                 objectDeleted = true;
  230.                 break;
  231.             }
  232.  
  233.             theTempDecafObject =
  234.                     theTempDecafObject.doGetNextDecafObject();
  235.         }
  236.  
  237.         return( objectDeleted );
  238.     }
  239.  
  240.     //    For creating a new object.
  241.     public boolean doAddDecafObject( int theType, 
  242.             String theString )
  243.     {
  244.         int                        theColor;
  245.         DecafObject        theTempDecafObject = theFirstDecafObject;
  246.  
  247.         //    Use links between objects to find the last one created.
  248.         while ( theTempDecafObject != null )
  249.         {
  250.             theTempDecafObject.DoSetSelected( false );        
  251.             theTempDecafObject =
  252.                     theTempDecafObject.doGetNextDecafObject();
  253.         }
  254.  
  255.         theNewDecafObject = new DecafObject();
  256.  
  257.         //    Setup the object references for our linked list.
  258.         if ( theCurrentDecafObject != null )
  259.         {
  260.             theNewDecafObject.doSetPreviousDecafObject( 
  261.                     theCurrentDecafObject );
  262.  
  263.             theCurrentDecafObject.doSetNextDecafObject( 
  264.                     theNewDecafObject );
  265.         }
  266.  
  267.         //    Set various properties for our new object.
  268.         //    Much of this code can be carefully moved to the DecafObject class 
  269.         //    as initialization code.
  270.         theNewDecafObject.DoSetObjectType( theType );
  271.  
  272.         switch ( theType )
  273.         {
  274.             case    0:
  275.                 theColor = this.doFindColor( 1 );
  276.                 theNewDecafObject.doSetBackColor( theColor );
  277.                 theColor = this.doFindColor( 2 );
  278.                 theNewDecafObject.doSetTextColor( theColor );
  279.                 theNewDecafObject.DoSetTextAlignment( 
  280.                         theLeftAlignment );
  281.                 thePanelID++;
  282.                 theNewDecafObject.DoSetID( thePanelID );
  283.                 break;
  284.  
  285.             case    1:
  286.                 theColor = this.doFindColor( 3 );
  287.                 theNewDecafObject.doSetBackColor( theColor );
  288.                 theColor = this.doFindColor( 4 );
  289.                 theNewDecafObject.doSetTextColor( theColor );
  290.                 theNewDecafObject.DoSetTextAlignment(
  291.                         theCenterAlignment );
  292.                 theButtonID++;
  293.                 theNewDecafObject.DoSetID( theButtonID );
  294.                 break;
  295.  
  296.             case    2:
  297.                 theColor = this.doFindColor( 5 );
  298.                 theNewDecafObject.doSetBackColor( theColor );
  299.                 theColor = this.doFindColor( 6 );
  300.                 theNewDecafObject.doSetTextColor( theColor );
  301.                 theNewDecafObject.DoSetTextAlignment(
  302.                         theLeftAlignment );
  303.                 theTextAreaID++;
  304.                 theNewDecafObject.DoSetID( theTextAreaID );
  305.                 break;
  306.  
  307.             default:
  308.                 break;
  309.         }
  310.  
  311.         if ( theType == 0 )
  312.         {
  313.             String    tempString = new String();
  314.  
  315.             theString = tempString.valueOf( thePanelID );
  316.         }
  317.  
  318.         theNewDecafObject.DoSetText( theString );
  319.         theNewDecafObject.DoSetupCanvasComponent();
  320.         theNewDecafObject.DoSetSelected( true );
  321.  
  322.         if ( theFirstDecafObject == null )
  323.             theFirstDecafObject = theNewDecafObject;
  324.  
  325.         theCurrentDecafObject = theNewDecafObject;
  326.  
  327.         return true;
  328.     }
  329.  
  330.     //    Override the Canvas paint event handler for painting all currently existing objects.
  331.     public void paint( Graphics g )
  332.     {
  333.         int                        theHeight = 0, theWidth = 0;
  334.         int                        theAscent = 0, theLeading = 0;
  335.         int                        i = 0, theMaxHeight;
  336.         int                        theXOffset = 1, theYOffset = 1;
  337.         FontMetrics        theFontMetrics;
  338.         Rectangle            theBounds = new Rectangle();
  339.         DecafObject        theTempDecafObject = theFirstDecafObject;
  340.  
  341.         //    Get font information for this piece of canvas.
  342.         //    We need it for drawing text within our objects.
  343.         theFontMetrics = g.getFontMetrics();
  344.         theHeight = theFontMetrics.getHeight();
  345.         theAscent = theFontMetrics.getAscent();
  346.         theLeading = theFontMetrics.getLeading();
  347.         theMaxHeight = theFontMetrics.getMaxAscent();
  348.  
  349.         //    Another case where we walk through our linked list of objects.
  350.         while ( theTempDecafObject != null )
  351.         {
  352.             theXOffset =  1;
  353.             theYOffset =  1;
  354.  
  355.             theBounds = theTempDecafObject.DoGetBounds();
  356.  
  357.             //    The bounding rectangle is used for determining if text fits within a button.
  358.             //    If not, adjust the bounds to center the text with a small buffer on each side.
  359.             if ( theTempDecafObject.DoGetObjectType() == 
  360.                     theButtonType )
  361.             {
  362.                 theWidth = theFontMetrics.stringWidth(
  363.                         theTempDecafObject.DoGetText() );
  364.  
  365.                 if ( theBounds.width < theWidth + 2 )
  366.                 {
  367.                     theBounds.width = theWidth + 2;
  368.                     theTempDecafObject.DoSetBounds( theBounds );
  369.                 }
  370.  
  371.                 theXOffset = ( theBounds.width - theWidth ) / 2;
  372.                 theYOffset = ( theBounds.height - theHeight ) / 2;
  373.             }
  374.  
  375.             //    Select the paint color and paint the object's outline.
  376.             g.setColor( theTempDecafObject.doGetBackColor() );
  377.  
  378.             if ( theTempDecafObject.DoGetSelected() )
  379.                 g.fill3DRect( theBounds.x, theBounds.y,
  380.                         theBounds.width, theBounds.height, true );
  381.             else
  382.                 g.drawRect( theBounds.x, theBounds.y,
  383.                         theBounds.width, theBounds.height );
  384.  
  385.             //    Select the paint color and paint the object's text.
  386.             g.setColor( theTempDecafObject.doGetTextColor() );
  387.  
  388.             switch    ( theTempDecafObject.DoGetObjectType() )
  389.             {
  390.                 case    0:
  391.                     g.drawString( theTempDecafObject.DoGetText(),
  392.                             theBounds.x + theXOffset, theBounds.y +
  393.                             theYOffset + theMaxHeight );
  394.                     break;
  395.  
  396.                 case    1:
  397.                     g.drawString( theTempDecafObject.DoGetText(),
  398.                             theBounds.x + theXOffset, theBounds.y +
  399.                             theYOffset + theAscent + theLeading );
  400.                     break;
  401.  
  402.                 case    2:
  403.                     g.drawString( theTempDecafObject.DoGetText(),
  404.                             theBounds.x + theXOffset, theBounds.y +
  405.                             theMaxHeight + theYOffset );
  406.                     break;
  407.             }
  408.  
  409.             theTempDecafObject =
  410.                     theTempDecafObject.doGetNextDecafObject();
  411.         }
  412.     }
  413.  
  414.     //    Override the Canvas mouseDown event handler.
  415.     public boolean mouseDown( Event evt, int x, int y )
  416.     {
  417.         int                        i = 0;
  418.         boolean                doRepaint = false, foundItem = false;
  419.         DecafObject        theTempDecafObject = theFirstDecafObject;
  420.         Rectangle            theBounds = new Rectangle();
  421.         boolean                isInside = false;
  422.  
  423.         //    Start with a clean slate (e.g. no objects selected).
  424.         while ( theTempDecafObject != null )
  425.         {
  426.             theTempDecafObject.DoSetSelected( false );
  427.             theTempDecafObject =
  428.                     theTempDecafObject.doGetNextDecafObject();
  429.         }
  430.  
  431.         //    Yet another walk through our object list.
  432.         //    Find the first object that contains the mouseDown location (x and y).
  433.         //    Check to see if the click is within our grow area for the object.
  434.         //    (The grow area size should be defined somewhere for easy modification.
  435.         //    It might be a property to make user-definable.)
  436.         //    Get the x and y offsets from the upper left corner of the object, so we can 
  437.         //    redraw it  in relation to where the mouseUp occurs.
  438.         //    Once we have found our object and set the appropriate values, exit the loop.
  439.  
  440.         theTempDecafObject = theFirstDecafObject;
  441.  
  442.         while ( theTempDecafObject != null )
  443.         {
  444.             theBounds = theTempDecafObject.DoGetBounds();
  445.  
  446.             if ( theBounds.inside( x, y ) )
  447.             {
  448.                 if ( ( x < theBounds.x + theBounds.width ) && 
  449.                         ( x > theBounds.x + theBounds.width - 5 ) &&
  450.                         ( y < theBounds.y + theBounds.height ) && 
  451.                         ( y > theBounds.y + theBounds.height - 5 ) )
  452.                             theTempDecafObject.DoSetInsideGrow( true );
  453.  
  454.                 xOffset = x - theBounds.x;
  455.                 yOffset = y - theBounds.y;
  456.             
  457.                 theTempDecafObject.DoSetSelected( true );
  458.                 isInside = true;
  459.                 foundItem = true;
  460.             }
  461.  
  462.             if ( foundItem )
  463.                 break;
  464.  
  465.             theTempDecafObject =
  466.                     theTempDecafObject.doGetNextDecafObject();
  467.         }
  468.  
  469.         mouseIsDown = true;
  470.         return true;
  471.     }
  472.  
  473.     //    Override the Canvas mouseUp event handler.
  474.     public boolean mouseUp( Event evt, int x, int y )
  475.     {
  476.         boolean                foundItem = false;
  477.         DecafObject        theTempDecafObject = theFirstDecafObject;
  478.         Rectangle            theBounds = new Rectangle();
  479.  
  480.         //    If we matched the coords of the mouseDown event, and the user is releasing the
  481.         //    button within our canvas, we will handle the mouseUp.
  482.         if ( mouseIsDown )
  483.         {
  484.             if ( this.inside( x, y ) )
  485.             {
  486.                 while ( theTempDecafObject != null )
  487.                 {
  488.                     //    Walk through the object list, looking for the selected object.
  489.                     //    Either move or resize the selected object, depending on where the
  490.                     //    mouseDown occured.
  491.                     if ( theTempDecafObject.DoGetSelected() )
  492.                     {
  493.                         theBounds = theTempDecafObject.DoGetBounds();
  494.  
  495.                         if ( theTempDecafObject.DoGetInsideGrow() )
  496.                             theBounds.resize( theBounds.width + ( x - 
  497.                                     ( theBounds.x + theBounds.width ) ),
  498.                                     theBounds.height + ( y - ( theBounds.y +
  499.                                     theBounds.height ) ) );
  500.                         else
  501.                             theBounds.move( x - xOffset, y - yOffset );
  502.  
  503.                         theTempDecafObject.DoSetBounds( theBounds );
  504.                         xOffset = 0;
  505.                         yOffset = 0;
  506.                         foundItem = true;
  507.                     }
  508.  
  509.                     theTempDecafObject.DoSetInsideGrow( false );
  510.  
  511.                     if ( foundItem )
  512.                         break;
  513.  
  514.                     theTempDecafObject = 
  515.                             theTempDecafObject.doGetNextDecafObject();
  516.                 }
  517.             }
  518.  
  519.             //    If we did not find a selected object matching the x and y coordinates, 
  520.             //    deselect all objects.
  521.             if ( !foundItem )
  522.             {
  523.                 theTempDecafObject = theFirstDecafObject;
  524.  
  525.                 while ( theTempDecafObject != null )
  526.                 {
  527.                     theTempDecafObject.DoSetSelected( false );
  528.                     theTempDecafObject = 
  529.                             theTempDecafObject.doGetNextDecafObject();
  530.                 }
  531.             }
  532.  
  533.             repaint();
  534.         }
  535.  
  536.         mouseIsDown = false;
  537.         return true;
  538.     }
  539.  
  540.